package net.sf.rose.business.bean.control.judge;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.jexl2.Expression;
import org.apache.commons.jexl2.JexlContext;
import org.apache.commons.jexl2.JexlEngine;
import org.apache.commons.jexl2.MapContext;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.ElementList;

/**
 * @author fengjian
 * @since 2014-5-25
 * 
 */
public class JudgeBean {

	private static JexlEngine JEXL = null;

	static {
		JEXL = new JexlEngine();
		JEXL.setCache(512);
	}

	/** 主键编号序列 */
	@Attribute
	private int count = 0;

	/** 条件判断依据列表 */
	@ElementList(required = false)
	private List<JudgeStatement> judges = null;

	public List<JudgeStatement> getJudges() {
		return judges;
	}

	public JudgeStatement getJudge(int id) {
		for (JudgeStatement statement : this.judges) {
			if (statement.getId() == id) {
				return statement;
			}
		}
		return null;
	}

	public void setJudges(List<JudgeStatement> judges) {
		this.judges = judges;
	}

	public void removeJudge(JudgeStatement judge) {
		for (int i = 0; i < judges.size(); i++) {
			if (judges.get(i).getId() == judge.getId()) {
				judges.remove(i);
				return;
			}
		}
	}

	public void removeJudge(int id) {
		for (int i = 0; i < judges.size(); i++) {
			if (judges.get(i).getId() == id) {
				judges.remove(i);
				return;
			}
		}
	}

	/**
	 * 添加判断依据
	 * 根据类型值大小顺序排序插入列表中
	 * 数据定义(4)排在最前面，工作组定义(1)排在最后面
	 * @param judge - 判断依据数据
	 */
	public void addJudge(JudgeStatement judge) {
		if (judges != null) {
			// 如果存在，则更新
			for (int i = 0; i < judges.size(); i++) {
				if (judges.get(i).getId() == judge.getId()) {
					judges.remove(i);
					judges.add(i, judge);
					return;
				}
			}
		}
		// 新增操作
		judge.setId(count);
		count++;
		if (judges == null) {
			judges = new ArrayList<JudgeStatement>();
			judges.add(judge);
		} else {
			for (int i = judges.size() - 1; i > -1; i--) {
				if (judge.getType() == judges.get(i).getType()) {
					judges.add(i, judge);
					return;
				}
			}
			judges.add(0, judge);
		}
	}

	/**
	 * 根据传入的判断依据数据集，依据规则执行判断，返回判断结果
	 * 判断优先级依次是：数据定义->用户定义->角色定义->工作组定义
	 * 判断执行过程如下：
	 * 1.遍历数据定义取最小值，如果值已经是隐藏(-1)，则直接返回“-1”
	 * 2.遍历用户定义取最小值，如果值已经是隐藏(-1)，则直接返回“-1”
	 * 3.用户定义的值不能大于数据定义的值；如果最终用户定义判断值是非未定义，则返回这个值
	 * 4.遍历角色定义取最大值，如果最终角色定义判断值是非未定义，则返回这个值
	 * 5.遍历工作组定义取最大值，如果最终工作组定义判断值是非未定义，则返回这个值
	 * @param map - 判断依据数据集
	 * @return 返回权限判断的结果值
	 * -1：隐藏,0：未定义,1：显示,2：编辑
	 */
	public int judge(Map<String, Object> map) {
		int val = 0;
		int role = 0;
		int group = 0;
		if (judges == null) {
			return val;
		}
		Expression expr;
		JexlContext jc = new MapContext(map);
		for (JudgeStatement judge : judges) {
			// 遍历数据定义，取最小值
			if (judge.getType() == 4) {
				expr = JEXL.createExpression(judge.getExpression());
				int i = (Integer) expr.evaluate(jc);
				if (i == -1)
					return -1;
				val = val == 0 ? i : (val < i ? val : i);
			}
			// 遍历用户定义，取非未定义的值
			else if (judge.getType() == 3) {
				expr = JEXL.createExpression(judge.getExpression());
				int i = (Integer) expr.evaluate(jc);
				if (i == -1)
					return -1;
				// 如果值为未定义(0)以外的值，则以此值依据判断，并不再计算以后的条件表达式。
				else if (i != 0) {
					// 与数据定义相比，取最小值
					val = val == 0 ? i : (val < i ? val : i);
					break;
				}
			}
			// 遍历角色定义，取非未定义的值，取最大值
			else if (judge.getType() == 2) {
				expr = JEXL.createExpression(judge.getExpression());
				int i = (Integer) expr.evaluate(jc);
				role = role == 0 ? i : (role > i ? role : i);
			}
			// 遍历工作组定义，取非未定义的值，取最大值
			else if (judge.getType() == 1) {
				expr = JEXL.createExpression(judge.getExpression());
				int i = (Integer) expr.evaluate(jc);
				group = group == 0 ? i : (group > i ? group : i);
			}
		}
		// 如果数据定义和用户定义判断项目都没有定义
		if (val == 0)
			val = role;
		// 如果数据定义、用户定义和角色定义判断项目都没有定义
		if (val == 0)
			val = group;
		return val;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		JudgeBean bean = new JudgeBean();
		JudgeStatement js = new JudgeStatement();
		js.setType(1);
		js.setExpression("1234");
		bean.addJudge(js);
		js = new JudgeStatement();
		js.setType(2);
		js.setExpression("12345");
		bean.addJudge(js);
		js = new JudgeStatement();
		js.setType(3);
		js.setExpression("123456");
		bean.addJudge(js);
		js = new JudgeStatement();
		js.setType(4);
		js.setExpression("1234567");
		bean.addJudge(js);
		js = new JudgeStatement();
		js.setType(4);
		js.setExpression("12345678");
		bean.addJudge(js);
		js = new JudgeStatement();
		js.setType(3);
		js.setExpression("123456789");
		bean.addJudge(js);
		System.out.print(bean);
		int i = 4;
		i = i > 2 ? 12 : 10;
	}
}
